package com.example.exam.utils;

import com.jfinal.kit.Kv;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class GenEntityMysql {

	private List<TableBean> tables = new ArrayList<TableBean>();

	
	private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	// TODO 需要修改的地方
//	private static final String URL = "jdbc:mysql://192.168.3.184:3306";
//	private static final String SCHEMA = "yqwj_manager";
//	private static final String NAME = "root";
//	private static final String PASS = "mysql@#>!*$";	
	
//	private static final String URL = "jdbc:mysql://192.168.3.120:3306";
//	private static final String SCHEMA = "zhihuianfang";
//	private static final String NAME = "guojx";
//	private static final String PASS = "gjx123@2019";
	
	
	private static final String URL = "jdbc:mysql://125.75.110.219:3306";
	private static final String SCHEMA = "equity_manager";
	private static final String NAME = "root";
	private static final String PASS = "Qs1jcsxdl@2020!";
	private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
	private String packageOutPath = "com.ftwj"; // 指定实体生成所在包的路径
	private String authorName = "LiBB"; // 作者名字
	// 指定需要生成的表的表名，全部生成设置为null
	// private String[] generateTables = null;
	private String[] removePrefix = {""};
	private String[] generateTables = {"sms_xf_log"};
	private String savePath = "D:\\TTTTT"; // 代码保存生成路径

	/**
	 * @return
	 * @description 生成class的所有内容
	 */
	private String parse(TableBean item) {
		StringBuffer sb = new StringBuffer();
		sb.append("package " + packageOutPath + ".entity;\r\n");
		sb.append("\r\n");
		sb.append("import java.io.Serializable;\r\n");
		// 判断是否导入工具包
		if (item.isHasDateColumn()) {
			sb.append("import java.util.Date;\r\n");
		}
		if (item.isHasBigDecimal()) {
			sb.append("import java.math.BigDecimal;\r\n");
			// sb.append("import java.sql.*;\r\n");
		}
		sb.append("\r\n");
		// 注释部分
		sb.append("/**\r\n");
		if (item.getTableComment() != null && item.getTableComment().equals("") == false) {
			sb.append(" * " + item.getTableComment() + "\r\n");
		}
		sb.append(" * table name:  " + item.getTableName() + "\r\n");
		sb.append(" * author name: " + authorName + "\r\n");
		sb.append(" * create time: " + SDF.format(new Date()) + "\r\n");
		sb.append(" */ \r\n");
		// 实体部分
		sb.append("public class " + item.getTableNameCapitalized() + "Bean" + " implements Serializable {\r\n\r\n");
		sb.append("\tprivate static final long serialVersionUID = 1L;");
		sb.append("\r\n");
		sb.append("\r\n");
		processAllAttrs(sb, item.getColumnBeanList()); // 属性
		sb.append("\r\n");
		processAllMethod(sb, item.getColumnBeanList()); // get set方法
		sb.append("\r\n}\r\n");
		return sb.toString();
	}

	/**
	 * @param sb
	 * @description 生成所有成员变量
	 */
	private void processAllAttrs(StringBuffer sb, List<ColumnBean> columns) {
		for (int i = 0; i < columns.size(); i++) {
			ColumnBean column = columns.get(i);
			if (column.getColumnComment() != null && column.getColumnComment().equals("") == false) {
				sb.append("\t//" + column.getColumnComment() + "\t\n");
			}
			sb.append("\tprivate " + column.getColumnType() + " " + column.getColumnNameNoDash() + ";\r\n");
		}
	}

	/**
	 * @param sb
	 * @description 生成所有get/set方法
	 */
	private void processAllMethod(StringBuffer sb, List<ColumnBean> columns) {
		for (int i = 0; i < columns.size(); i++) {
			ColumnBean bean = columns.get(i);
			sb.append("\tpublic void set" + bean.getColumnNameCapitalized() + "(" + bean.getColumnType() + " "
					+ bean.getColumnNameNoDash() + "){\r\n");
			sb.append("\t\tthis." + bean.getColumnNameNoDash() + "=" + bean.getColumnNameNoDash() + ";\r\n");
			sb.append("\t}\r\n");
			sb.append("\tpublic " + bean.getColumnType() + " get" + bean.getColumnNameCapitalized() + "(){\r\n");
			sb.append("\t\treturn " + bean.getColumnNameNoDash() + ";\r\n");
			sb.append("\t}\r\n");
		}
	}

	/**
	 * @param str
	 *            传入字符串
	 * @description 将传入字符串的首字母转成大写
	 */
	private String initCap(String str) {
		char[] ch = str.toCharArray();
		if (ch[0] >= 'a' && ch[0] <= 'z')
			ch[0] = (char) (ch[0] - 32);
		return new String(ch);
	}

	/**
	 * @description 将mysql中表名和字段名转换成驼峰形式
	 */
	private String getTransStr(String before, boolean firstChar2Upper) {
		// 不带"_"的字符串,则直接首字母大写后返回
		if (!before.contains("_"))
			return firstChar2Upper ? initCap(before) : before;
		String[] strs = before.split("_");
		StringBuffer after = null;
		if (firstChar2Upper) {
			after = new StringBuffer(initCap(strs[0]));
		} else {
			after = new StringBuffer(strs[0]);
		}
		if (strs.length > 1) {
			for (int i = 1; i < strs.length; i++)
				after.append(initCap(strs[i]));
		}
		return after.toString();
	}

	/**
	 * @description 查找sql字段类型所对应的Java类型
	 */
	private String sqlType2JavaType(String sqlType) {
		if (sqlType.equalsIgnoreCase("bit")) {
			return "Boolean";
		} else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("tinyint")
				|| sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase("mediumint")) {
			return "Integer";
		} else if (sqlType.equalsIgnoreCase("bigint")) {
			return "Long";
		} else if (sqlType.equalsIgnoreCase("float")) {
			return "Float";
		} else if (sqlType.equalsIgnoreCase("real") || sqlType.equalsIgnoreCase("double")
				|| sqlType.equalsIgnoreCase("smallmoney")) {
			return "Double";
		} else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
				|| sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
			return "BigDecimal";
		} else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char")
				|| sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")
				|| sqlType.equalsIgnoreCase("text") || sqlType.equalsIgnoreCase("longtext")
				|| sqlType.equalsIgnoreCase("enum")) {
			return "String";
		} else if (sqlType.equalsIgnoreCase("datetime") || sqlType.equalsIgnoreCase("timestamp")
				|| sqlType.equalsIgnoreCase("date")) {
			return "Date";
		} else if (sqlType.equalsIgnoreCase("image")) {
			return "Blod";
		}
		return sqlType;
	}

	/**
	 * 生成方法
	 */
	private void generate() throws Exception {
		// 与数据库的连接
		Connection con;
		Class.forName(DRIVER);
		con = DriverManager.getConnection(URL, NAME, PASS);
		System.out.println("connect database success...");
		// 获取数据库的元数据
		DatabaseMetaData db = con.getMetaData();
		// 是否有指定生成表，有指定则直接用指定表，没有则全表生成
		if (generateTables == null) {
			// 从元数据中获取到所有的表名
			ResultSet rs = db.getTables(SCHEMA, null, "%", new String[] { "TABLE" });
			while (rs.next()) {
				TableBean bean = new TableBean();
				bean.setTableName(rs.getString(3));
				initClassName(bean);
				bean.setTableComment(rs.getString(5));
				tables.add(bean);
			}
		} else {
			for (String tableName : generateTables) {
				TableBean bean = new TableBean();
				bean.setTableName(tableName);
				initClassName(bean);
				// 表注释
				ResultSet rs = db.getTables(SCHEMA, null, tableName, new String[] { "TABLE" });
				if (rs.next()) {
					bean.setTableComment(rs.getString(5));
				}
				tables.add(bean);
			}
		}
		PrintWriter pw = null;
		JfEnjoy jf = new JfEnjoy();
		for (int j = 0; j < tables.size(); j++) {
			TableBean item = tables.get(j);
			// 获取主键字段名
			String keyName = "id";
			ResultSet pkRs = db.getPrimaryKeys(SCHEMA, SCHEMA, item.getTableName());
			while (pkRs.next()) {
				for (int m = 1; m <= 6; m++) {
					System.out.println("----------------1111111---------------" + pkRs.getString(m));
				}
				keyName = pkRs.getString(4);
			}
			ResultSet rs = db.getColumns(null, "%", item.getTableName(), "%");
			List<ColumnBean> columns = new ArrayList<ColumnBean>();
			item.setColumnBeanList(columns);
			while (rs.next()) {
				
				ColumnBean columnBean = new ColumnBean();
				columnBean.setColumnName(rs.getString("COLUMN_NAME"));
				columnBean.setColumnNameNoDash(getTransStr(columnBean.getColumnName(), false));
				columnBean.setColumnNameCapitalized(getTransStr(columnBean.getColumnName(), true));
				columnBean.setColumnComment(rs.getString("REMARKS"));
				String typeName = rs.getString("TYPE_NAME");
				typeName = sqlType2JavaType(typeName);
				if (typeName.equalsIgnoreCase("date")) {
					item.setHasDateColumn(true);
				} else if (typeName.equalsIgnoreCase("BigDecimal")) {
					item.setHasBigDecimal(true);
				}
				if (typeName.equalsIgnoreCase("Blod")) {
				}
				columnBean.setColumnType(typeName);
				columns.add(columnBean);
				// 获取主键类型  
				if (keyName.equals(columnBean.getColumnName())) {
					item.setPrimaryKey(columnBean);
				}  
			}
			if (item.getPrimaryKey() == null) {
				continue;
			}
			// 解析生成class的所有内容
			String content = parse(item);
			// 输出生成文件
			String dirName = "";
			if ("".equals(savePath) == false) {
				dirName = savePath + "/" + packageOutPath + ".entity";
				dirName = dirName.replace(".", "/");
			} else {
				// 默认路径
				File directory = new File("");
				dirName = directory.getAbsolutePath() + "/src/main/java/"
						+ (packageOutPath + ".entity").replace(".", "/");
			}
			System.out.println("---输出路径：----"+dirName+"---------");
			File dir = new File(dirName);
			if (!dir.exists() && dir.mkdirs())
				System.out.println("generate dir 【" + dirName + "】");
			String javaPath = dirName + "/" + item.getTableNameCapitalized() + "Bean.java";
			FileWriter fw = new FileWriter(javaPath);
			pw = new PrintWriter(fw);
			pw.println(content);
			pw.flush();
			pw.close();
			System.out.println("create class for 【" + item.getTableName() + "】");
			// 生成dao
			Kv kv = Kv.by("tableBean", item).set("packageBase", packageOutPath);
			jf.render("Daoimpl.txt", kv,
					dirName.replace("/entity", "/dao") + "/" + item.getTableNameCapitalized() + "Dao.java");
		}
	}

	private void initClassName(TableBean bean) {
		bean.setClassName(bean.getTableName());
		for (String item : removePrefix) {
			String prefix = item + "_";
			if (bean.getClassName().startsWith(prefix)) {
				bean.setClassName(bean.getClassName().replace(prefix, ""));
				break;
			}
		}
		bean.setTableNameNoDash(getTransStr(bean.getClassName(), false));
		bean.setTableNameCapitalized(getTransStr(bean.getClassName(), true));
	}

	/**
	 * @param args
	 * @description 执行方法
	 */
	public static void main(String[] args) {
		try {
			new GenEntityMysql().generate();
			System.out.println("generate classes success!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
